package utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;

/**
 * websocket推流工具类
 *
 * @author zjh
 */
@Component
public class WebSocketUtil {

    private static CMDUtil cmdUtil;

    @Autowired
    public void setUserRepository(CMDUtil cmdUtil) {
        WebSocketUtil.cmdUtil = cmdUtil;
    }

    private static final HashMap<String, Process> RTSP_TASK = new HashMap<>();
    private static final HashMap<String, Integer> RTSP_PUSH_COUNT = new HashMap<>();
    private static final HashMap<String, String> RTSP_PUSH_ADDR = new HashMap<>();

    private static volatile Integer ADDR = 0;

    private static final String COMMAND = "ffmpeg -i \"%s\" -q 0 -f mpegts -codec:v mpeg1video -s 320x240 http://127.0.0.1:8081/supersecret/%s";

    private static final String THREAD_NAME1 = "_inputStream";
    private static final String THREAD_NAME2 = "_errorStream";

    public synchronized static String push(String rtspUrl) {
        Integer count = RTSP_PUSH_COUNT.get(rtspUrl);
        if (count != null && count > 0) {
            RTSP_PUSH_COUNT.put(rtspUrl, ++count);
            return RTSP_PUSH_ADDR.get(rtspUrl);
        }
        ADDR++;
        Process process = utils.TaskUtils.schedule(rtspUrl, () -> {
            String result = String.format(COMMAND, rtspUrl, ADDR + "");
            return cmdUtil.excuteCMDCommand(result);
        }, 0);

        if (process == null) {
            throw new RuntimeException("推流失败");
        }

        utils.TaskUtils.schedule(rtspUrl + THREAD_NAME1, getTask(process.getInputStream()), 0);
        utils.TaskUtils.schedule(rtspUrl + THREAD_NAME2, getTask(process.getErrorStream()), 0);

        RTSP_PUSH_COUNT.put(rtspUrl, 1);
        RTSP_TASK.put(rtspUrl, process);
        RTSP_PUSH_ADDR.put(rtspUrl, ADDR + "");
        return ADDR + "";
    }

    public synchronized static void close(String rtspUrl) {
        Integer count = RTSP_PUSH_COUNT.get(rtspUrl);
        if (count == null || count == 0) {
            return;
        }
        count--;
        RTSP_PUSH_COUNT.put(rtspUrl, count);
        if (count > 0) {
            return;
        }

        utils.TaskUtils.remove(rtspUrl);
        utils.TaskUtils.remove(rtspUrl + THREAD_NAME1);
        utils.TaskUtils.remove(rtspUrl + THREAD_NAME2);
        utils.TaskUtils.remove(rtspUrl);
        Process process = RTSP_TASK.get(rtspUrl);
        if (process != null) {
            cmdUtil.killProcessTree(process, rtspUrl);
        }
    }

    private static Runnable getTask(InputStream inputStream) {
        return () -> {
            InputStreamReader inputStreamReader = null;
            BufferedReader br = null;
            try {
                inputStreamReader = new InputStreamReader(
                        inputStream);
                br = new BufferedReader(inputStreamReader);
                // 打印信息
//            String line = null;
//            while ((line = br.readLine()) != null) {
//                System.out.println(line);
//            }
                // 不打印信息
                while (br.readLine() != null) ;
            } catch (IOException ioe) {
                ioe.printStackTrace();
            } finally {
                try {
                    if (br != null) {
                        br.close();
                    }
                    if (inputStreamReader != null) {
                        inputStreamReader.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        };
    }

    public static void closeAll() {
        RTSP_TASK.keySet().forEach(utils.WebSocketUtil::close);
    }
}
